import { ref, watch, computed, type Ref } from 'vue'
import { ElMessage } from 'element-plus'

// 存储类型
type StorageType = 'localStorage' | 'sessionStorage'

// 序列化器接口
interface Serializer<T> {
  read: (value: string) => T
  write: (value: T) => string
}

// 存储配置接口
interface StorageConfig<T> {
  defaultValue?: T
  serializer?: Serializer<T>
  onError?: (error: Error) => void
  syncAcrossTabs?: boolean
  debounceMs?: number
}

// 默认序列化器
const defaultSerializer: Serializer<any> = {
  read: (value: string) => {
    try {
      return JSON.parse(value)
    } catch {
      return value
    }
  },
  write: (value: any) => {
    try {
      return JSON.stringify(value)
    } catch {
      return String(value)
    }
  }
}

// 字符串序列化器
const stringSerializer: Serializer<string> = {
  read: (value: string) => value,
  write: (value: string) => value
}

// 数字序列化器
const numberSerializer: Serializer<number> = {
  read: (value: string) => Number(value),
  write: (value: number) => String(value)
}

// 布尔序列化器
const booleanSerializer: Serializer<boolean> = {
  read: (value: string) => value === 'true',
  write: (value: boolean) => String(value)
}

// 检查存储是否可用
const isStorageAvailable = (type: StorageType): boolean => {
  if (typeof window === 'undefined') return false
  
  try {
    const storage = window[type]
    const testKey = '__storage_test__'
    storage.setItem(testKey, 'test')
    storage.removeItem(testKey)
    return true
  } catch {
    return false
  }
}

// 获取存储对象
const getStorage = (type: StorageType): Storage | null => {
  if (!isStorageAvailable(type)) return null
  return window[type]
}

// 防抖函数
const debounce = <T extends (...args: any[]) => any>(
  func: T,
  wait: number
): T => {
  let timeout: NodeJS.Timeout | null = null
  
  return ((...args: Parameters<T>) => {
    if (timeout) clearTimeout(timeout)
    timeout = setTimeout(() => func(...args), wait)
  }) as T
}

// 本地存储 Composable
export const useStorage = <T>(
  key: string,
  defaultValue: T,
  storageType: StorageType = 'localStorage',
  config: StorageConfig<T> = {}
) => {
  const {
    serializer = defaultSerializer,
    onError = (error) => {
      console.error('Storage error:', error)
      ElMessage.error('存储操作失败')
    },
    syncAcrossTabs = true,
    debounceMs = 100
  } = config
  
  const storage = getStorage(storageType)
  
  // 读取存储值
  const readFromStorage = (): T => {
    if (!storage) return defaultValue
    
    try {
      const value = storage.getItem(key)
      if (value === null) return defaultValue
      return serializer.read(value)
    } catch (error) {
      onError(error as Error)
      return defaultValue
    }
  }
  
  // 写入存储值
  const writeToStorage = (value: T): void => {
    if (!storage) return
    
    try {
      if (value === null || value === undefined) {
        storage.removeItem(key)
      } else {
        storage.setItem(key, serializer.write(value))
      }
    } catch (error) {
      onError(error as Error)
    }
  }
  
  // 创建响应式引用
  const storedValue = ref<T>(readFromStorage())
  
  // 防抖写入函数
  const debouncedWrite = debounceMs > 0 
    ? debounce(writeToStorage, debounceMs)
    : writeToStorage
  
  // 监听值变化并同步到存储
  watch(
    storedValue,
    (newValue) => {
      debouncedWrite(newValue)
    },
    { deep: true }
  )
  
  // 跨标签页同步
  if (syncAcrossTabs && typeof window !== 'undefined') {
    const handleStorageChange = (e: StorageEvent) => {
      if (e.key === key && e.newValue !== null) {
        try {
          const newValue = serializer.read(e.newValue)
          storedValue.value = newValue
        } catch (error) {
          onError(error as Error)
        }
      }
    }
    
    window.addEventListener('storage', handleStorageChange)
    
    // 清理函数
    const cleanup = () => {
      window.removeEventListener('storage', handleStorageChange)
    }
    
    // 在组件卸载时清理
    if (typeof window !== 'undefined' && 'onbeforeunload' in window) {
      window.addEventListener('beforeunload', cleanup)
    }
  }
  
  // 手动同步
  const sync = () => {
    storedValue.value = readFromStorage()
  }
  
  // 重置为默认值
  const reset = () => {
    storedValue.value = defaultValue
  }
  
  // 删除存储项
  const remove = () => {
    if (storage) {
      try {
        storage.removeItem(key)
        storedValue.value = defaultValue
      } catch (error) {
        onError(error as Error)
      }
    }
  }
  
  return {
    value: storedValue as Ref<T>,
    sync,
    reset,
    remove
  }
}

// 本地存储快捷方法
export const useLocalStorage = <T>(
  key: string,
  defaultValue: T,
  config?: StorageConfig<T>
) => {
  return useStorage(key, defaultValue, 'localStorage', config)
}

// 会话存储快捷方法
export const useSessionStorage = <T>(
  key: string,
  defaultValue: T,
  config?: StorageConfig<T>
) => {
  return useStorage(key, defaultValue, 'sessionStorage', config)
}

// 存储管理器
export const useStorageManager = (storageType: StorageType = 'localStorage') => {
  const storage = getStorage(storageType)
  
  // 获取所有键
  const getAllKeys = (): string[] => {
    if (!storage) return []
    
    const keys: string[] = []
    for (let i = 0; i < storage.length; i++) {
      const key = storage.key(i)
      if (key) keys.push(key)
    }
    return keys
  }
  
  // 获取所有项
  const getAllItems = (): Record<string, string> => {
    if (!storage) return {}
    
    const items: Record<string, string> = {}
    const keys = getAllKeys()
    
    keys.forEach(key => {
      const value = storage.getItem(key)
      if (value !== null) {
        items[key] = value
      }
    })
    
    return items
  }
  
  // 批量设置
  const setItems = (items: Record<string, any>): void => {
    if (!storage) return
    
    Object.entries(items).forEach(([key, value]) => {
      try {
        storage.setItem(key, defaultSerializer.write(value))
      } catch (error) {
        console.error(`Failed to set item ${key}:`, error)
      }
    })
  }
  
  // 批量删除
  const removeItems = (keys: string[]): void => {
    if (!storage) return
    
    keys.forEach(key => {
      try {
        storage.removeItem(key)
      } catch (error) {
        console.error(`Failed to remove item ${key}:`, error)
      }
    })
  }
  
  // 清空存储
  const clear = (): void => {
    if (!storage) return
    
    try {
      storage.clear()
    } catch (error) {
      console.error('Failed to clear storage:', error)
    }
  }
  
  // 获取存储大小（近似值）
  const getSize = (): number => {
    if (!storage) return 0
    
    let size = 0
    const items = getAllItems()
    
    Object.entries(items).forEach(([key, value]) => {
      size += key.length + value.length
    })
    
    return size
  }
  
  // 获取存储使用情况
  const getUsage = (): { used: number; total: number; percentage: number } => {
    const used = getSize()
    // 大多数浏览器的 localStorage 限制约为 5-10MB
    const total = 5 * 1024 * 1024 // 5MB
    const percentage = (used / total) * 100
    
    return { used, total, percentage }
  }
  
  // 检查键是否存在
  const hasKey = (key: string): boolean => {
    if (!storage) return false
    return storage.getItem(key) !== null
  }
  
  // 获取键的过期时间（如果使用了过期机制）
  const getExpiry = (key: string): number | null => {
    if (!storage) return null
    
    try {
      const expiryKey = `${key}_expiry`
      const expiry = storage.getItem(expiryKey)
      return expiry ? Number(expiry) : null
    } catch {
      return null
    }
  }
  
  // 设置带过期时间的值
  const setWithExpiry = (key: string, value: any, expiryMs: number): void => {
    if (!storage) return
    
    try {
      const expiryTime = Date.now() + expiryMs
      storage.setItem(key, defaultSerializer.write(value))
      storage.setItem(`${key}_expiry`, String(expiryTime))
    } catch (error) {
      console.error(`Failed to set item with expiry ${key}:`, error)
    }
  }
  
  // 获取带过期检查的值
  const getWithExpiry = <T>(key: string): T | null => {
    if (!storage) return null
    
    try {
      const expiryTime = getExpiry(key)
      if (expiryTime && Date.now() > expiryTime) {
        // 已过期，删除相关项
        storage.removeItem(key)
        storage.removeItem(`${key}_expiry`)
        return null
      }
      
      const value = storage.getItem(key)
      return value ? defaultSerializer.read(value) : null
    } catch (error) {
      console.error(`Failed to get item with expiry ${key}:`, error)
      return null
    }
  }
  
  // 清理过期项
  const clearExpired = (): number => {
    if (!storage) return 0
    
    let count = 0
    const keys = getAllKeys()
    const expiryKeys = keys.filter(key => key.endsWith('_expiry'))
    
    expiryKeys.forEach(expiryKey => {
      const originalKey = expiryKey.replace('_expiry', '')
      const expiryTime = getExpiry(originalKey)
      
      if (expiryTime && Date.now() > expiryTime) {
        storage.removeItem(originalKey)
        storage.removeItem(expiryKey)
        count++
      }
    })
    
    return count
  }
  
  return {
    // 基本操作
    getAllKeys,
    getAllItems,
    setItems,
    removeItems,
    clear,
    hasKey,
    
    // 存储信息
    getSize,
    getUsage,
    
    // 过期机制
    setWithExpiry,
    getWithExpiry,
    getExpiry,
    clearExpired,
    
    // 存储类型
    storageType: computed(() => storageType),
    isAvailable: computed(() => isStorageAvailable(storageType))
  }
}

// 存储工具函数
export const storageUtils = {
  // 序列化器
  serializers: {
    default: defaultSerializer,
    string: stringSerializer,
    number: numberSerializer,
    boolean: booleanSerializer
  },
  
  // 检查存储可用性
  isAvailable: isStorageAvailable,
  
  // 获取存储对象
  getStorage,
  
  // 创建自定义序列化器
  createSerializer: <T>(
    read: (value: string) => T,
    write: (value: T) => string
  ): Serializer<T> => ({ read, write }),
  
  // 存储大小格式化
  formatSize: (bytes: number): string => {
    const units = ['B', 'KB', 'MB', 'GB']
    let size = bytes
    let unitIndex = 0
    
    while (size >= 1024 && unitIndex < units.length - 1) {
      size /= 1024
      unitIndex++
    }
    
    return `${size.toFixed(2)} ${units[unitIndex]}`
  },
  
  // 存储配额检查
  checkQuota: async (): Promise<{ used: number; total: number } | null> => {
    if (typeof navigator !== 'undefined' && 'storage' in navigator && 'estimate' in navigator.storage) {
      try {
        const estimate = await navigator.storage.estimate()
        return {
          used: estimate.usage || 0,
          total: estimate.quota || 0
        }
      } catch {
        return null
      }
    }
    return null
  }
}

// 导出类型
export type { StorageType, Serializer, StorageConfig }